package cn.h8k.hj212.config;

import cn.h8k.hj212.version.ProtocolVersion;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * HJ212解析库配置类
 * 提供灵活的配置选项
 * 
 * @author HJ212 Team
 * @since 1.0
 */
public class Hj212Config {
    
    // 默认配置值
    private static final boolean DEFAULT_ENABLE_CACHE = true;
    private static final boolean DEFAULT_ENABLE_VALIDATION = true;
    private static final boolean DEFAULT_ENABLE_PLUGINS = true;
    private static final int DEFAULT_CACHE_SIZE = 1000;
    private static final long DEFAULT_CACHE_TTL = 3600000; // 1小时
    private static final ProtocolVersion DEFAULT_VERSION = ProtocolVersion.HJ212_2017;
    
    // 配置属性
    private boolean enableCache = DEFAULT_ENABLE_CACHE;
    private boolean enableValidation = DEFAULT_ENABLE_VALIDATION;
    private boolean enablePlugins = DEFAULT_ENABLE_PLUGINS;
    private boolean enableLengthValidation = true;
    private boolean enableCrcValidation = true;
    private int cacheSize = DEFAULT_CACHE_SIZE;
    private long cacheTtl = DEFAULT_CACHE_TTL;
    private ProtocolVersion defaultVersion = DEFAULT_VERSION;
    private final Map<String, Object> customProperties = new HashMap<>();
    
    /**
     * 默认构造函数
     */
    public Hj212Config() {
    }
    
    /**
     * 从Properties构造配置
     * @param properties 属性配置
     */
    public Hj212Config(Properties properties) {
        loadFromProperties(properties);
    }
    
    /**
     * 从Map构造配置
     * @param configMap 配置映射
     */
    public Hj212Config(Map<String, Object> configMap) {
        loadFromMap(configMap);
    }
    
    /**
     * 创建默认配置
     * @return 默认配置实例
     */
    public static Hj212Config createDefault() {
        return new Hj212Config();
    }
    
    /**
     * 创建高性能配置
     * @return 高性能配置实例
     */
    public static Hj212Config createHighPerformance() {
        Hj212Config config = new Hj212Config();
        config.setEnableCache(true);
        config.setEnableValidation(false); // 禁用详细验证以提高性能
        config.setEnablePlugins(false);    // 禁用插件以提高性能
        config.setCacheSize(5000);         // 增大缓存
        return config;
    }
    
    /**
     * 创建严格验证配置
     * @return 严格验证配置实例
     */
    public static Hj212Config createStrictValidation() {
        Hj212Config config = new Hj212Config();
        config.setEnableCache(false);      // 禁用缓存确保每次都验证
        config.setEnableValidation(true);
        config.setEnablePlugins(true);
        config.setEnableLengthValidation(true);
        config.setEnableCrcValidation(true);
        return config;
    }
    
    /**
     * 创建测试配置
     * @return 测试配置实例
     */
    public static Hj212Config createTest() {
        Hj212Config config = new Hj212Config();
        config.setEnableCache(false);
        config.setEnableValidation(false);
        config.setEnablePlugins(false);
        config.setEnableLengthValidation(false);
        config.setEnableCrcValidation(false);
        return config;
    }
    
    /**
     * 从Properties加载配置
     * @param properties 属性配置
     */
    public void loadFromProperties(Properties properties) {
        if (properties == null) {
            return;
        }
        
        enableCache = Boolean.parseBoolean(properties.getProperty("hj212.cache.enabled", String.valueOf(DEFAULT_ENABLE_CACHE)));
        enableValidation = Boolean.parseBoolean(properties.getProperty("hj212.validation.enabled", String.valueOf(DEFAULT_ENABLE_VALIDATION)));
        enablePlugins = Boolean.parseBoolean(properties.getProperty("hj212.plugins.enabled", String.valueOf(DEFAULT_ENABLE_PLUGINS)));
        enableLengthValidation = Boolean.parseBoolean(properties.getProperty("hj212.validation.length", "true"));
        enableCrcValidation = Boolean.parseBoolean(properties.getProperty("hj212.validation.crc", "true"));
        
        try {
            cacheSize = Integer.parseInt(properties.getProperty("hj212.cache.size", String.valueOf(DEFAULT_CACHE_SIZE)));
        } catch (NumberFormatException e) {
            cacheSize = DEFAULT_CACHE_SIZE;
        }
        
        try {
            cacheTtl = Long.parseLong(properties.getProperty("hj212.cache.ttl", String.valueOf(DEFAULT_CACHE_TTL)));
        } catch (NumberFormatException e) {
            cacheTtl = DEFAULT_CACHE_TTL;
        }
        
        String versionStr = properties.getProperty("hj212.version.default", DEFAULT_VERSION.getShortName());
        defaultVersion = ProtocolVersion.fromShortName(versionStr);
        
        // 加载自定义属性
        for (String key : properties.stringPropertyNames()) {
            if (key.startsWith("hj212.custom.")) {
                customProperties.put(key.substring("hj212.custom.".length()), properties.getProperty(key));
            }
        }
    }
    
    /**
     * 从Map加载配置
     * @param configMap 配置映射
     */
    public void loadFromMap(Map<String, Object> configMap) {
        if (configMap == null) {
            return;
        }
        
        enableCache = getBoolean(configMap, "enableCache", DEFAULT_ENABLE_CACHE);
        enableValidation = getBoolean(configMap, "enableValidation", DEFAULT_ENABLE_VALIDATION);
        enablePlugins = getBoolean(configMap, "enablePlugins", DEFAULT_ENABLE_PLUGINS);
        enableLengthValidation = getBoolean(configMap, "enableLengthValidation", true);
        enableCrcValidation = getBoolean(configMap, "enableCrcValidation", true);
        cacheSize = getInteger(configMap, "cacheSize", DEFAULT_CACHE_SIZE);
        cacheTtl = getLong(configMap, "cacheTtl", DEFAULT_CACHE_TTL);
        
        Object versionObj = configMap.get("defaultVersion");
        if (versionObj instanceof ProtocolVersion) {
            defaultVersion = (ProtocolVersion) versionObj;
        } else if (versionObj instanceof String) {
            defaultVersion = ProtocolVersion.fromShortName((String) versionObj);
        }
        
        // 加载自定义属性
        Object customObj = configMap.get("customProperties");
        if (customObj instanceof Map) {
            @SuppressWarnings("unchecked")
            Map<String, Object> customMap = (Map<String, Object>) customObj;
            customProperties.putAll(customMap);
        }
    }
    
    /**
     * 转换为Properties
     * @return Properties对象
     */
    public Properties toProperties() {
        Properties properties = new Properties();
        properties.setProperty("hj212.cache.enabled", String.valueOf(enableCache));
        properties.setProperty("hj212.validation.enabled", String.valueOf(enableValidation));
        properties.setProperty("hj212.plugins.enabled", String.valueOf(enablePlugins));
        properties.setProperty("hj212.validation.length", String.valueOf(enableLengthValidation));
        properties.setProperty("hj212.validation.crc", String.valueOf(enableCrcValidation));
        properties.setProperty("hj212.cache.size", String.valueOf(cacheSize));
        properties.setProperty("hj212.cache.ttl", String.valueOf(cacheTtl));
        properties.setProperty("hj212.version.default", defaultVersion.getShortName());
        
        // 添加自定义属性
        for (Map.Entry<String, Object> entry : customProperties.entrySet()) {
            properties.setProperty("hj212.custom." + entry.getKey(), String.valueOf(entry.getValue()));
        }
        
        return properties;
    }
    
    /**
     * 转换为Map
     * @return Map对象
     */
    public Map<String, Object> toMap() {
        Map<String, Object> map = new HashMap<>();
        map.put("enableCache", enableCache);
        map.put("enableValidation", enableValidation);
        map.put("enablePlugins", enablePlugins);
        map.put("enableLengthValidation", enableLengthValidation);
        map.put("enableCrcValidation", enableCrcValidation);
        map.put("cacheSize", cacheSize);
        map.put("cacheTtl", cacheTtl);
        map.put("defaultVersion", defaultVersion);
        map.put("customProperties", new HashMap<>(customProperties));
        return map;
    }
    
    // Getter和Setter方法
    public boolean isEnableCache() { return enableCache; }
    public void setEnableCache(boolean enableCache) { this.enableCache = enableCache; }
    
    public boolean isEnableValidation() { return enableValidation; }
    public void setEnableValidation(boolean enableValidation) { this.enableValidation = enableValidation; }
    
    public boolean isEnablePlugins() { return enablePlugins; }
    public void setEnablePlugins(boolean enablePlugins) { this.enablePlugins = enablePlugins; }
    
    public boolean isEnableLengthValidation() { return enableLengthValidation; }
    public void setEnableLengthValidation(boolean enableLengthValidation) { this.enableLengthValidation = enableLengthValidation; }
    
    public boolean isEnableCrcValidation() { return enableCrcValidation; }
    public void setEnableCrcValidation(boolean enableCrcValidation) { this.enableCrcValidation = enableCrcValidation; }
    
    public int getCacheSize() { return cacheSize; }
    public void setCacheSize(int cacheSize) { this.cacheSize = cacheSize; }
    
    public long getCacheTtl() { return cacheTtl; }
    public void setCacheTtl(long cacheTtl) { this.cacheTtl = cacheTtl; }
    
    public ProtocolVersion getDefaultVersion() { return defaultVersion; }
    public void setDefaultVersion(ProtocolVersion defaultVersion) { this.defaultVersion = defaultVersion; }
    
    public Map<String, Object> getCustomProperties() { return new HashMap<>(customProperties); }
    public void setCustomProperty(String key, Object value) { customProperties.put(key, value); }
    public Object getCustomProperty(String key) { return customProperties.get(key); }
    
    // 辅助方法
    private boolean getBoolean(Map<String, Object> map, String key, boolean defaultValue) {
        Object value = map.get(key);
        if (value instanceof Boolean) {
            return (Boolean) value;
        } else if (value instanceof String) {
            return Boolean.parseBoolean((String) value);
        }
        return defaultValue;
    }
    
    private int getInteger(Map<String, Object> map, String key, int defaultValue) {
        Object value = map.get(key);
        if (value instanceof Integer) {
            return (Integer) value;
        } else if (value instanceof String) {
            try {
                return Integer.parseInt((String) value);
            } catch (NumberFormatException e) {
                return defaultValue;
            }
        }
        return defaultValue;
    }
    
    private long getLong(Map<String, Object> map, String key, long defaultValue) {
        Object value = map.get(key);
        if (value instanceof Long) {
            return (Long) value;
        } else if (value instanceof String) {
            try {
                return Long.parseLong((String) value);
            } catch (NumberFormatException e) {
                return defaultValue;
            }
        }
        return defaultValue;
    }
}
